package com.zfei.gfb.service;

import cn.hutool.core.util.IdUtil;
import com.google.gson.JsonObject;
import com.zfei.gfb.api.InboxService;
import com.zfei.gfb.api.TalkService;
import com.zfei.gfb.api.domain.*;
import com.zfei.gfb.bean.StatusException;
import com.zfei.gfb.model.TalkEventEntity;
import com.zfei.gfb.repo.TalkRepo;
import com.zfei.gfb.util.Gsons;
import com.zfei.gfb.util.Now;
import com.zfei.gfb.util.TalkUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
 * @author fgh
 */
@Service("talkService")
public class TalkServiceImpl implements TalkService {

    private static final Logger logger = LoggerFactory.getLogger(TalkServiceImpl.class);

    @Resource
    private TalkRepo talkRepo;

    @Resource
    private InboxService inboxService;

    @Override
    public EventTuple createEvent(TalkEvent event) {
        TalkUtil.checkEvent(event);
        if (event.getEventId() == null) {
            event.setEventId(IdUtil.simpleUUID());
        }
        if (this.talkRepo.createEvent(event) > 0) {
//            this.talkLogic.postCreateEvent(event);
            return event.tuple();
        }

        return null;
    }


    @Override
    public String deleteEvent(String eventId) {
        return this.deleteEvent(new Update(eventId, EventUpdateType.DELETE_BY_SELF));
    }

    @Override
    public String deleteEvent(Update update) {
        TalkEventEntity entity = this.talkRepo.getTalkEventDao().get(update.getId());
        if (entity != null && entity.getDeleteTime() == 0) {
            long now = Now.millis();
            update.setTime(now);
            String ups = Gsons.toJson(update);

            JsonObject ext = Gsons.parseJsonObject(entity.getExt());
            TalkUtil.auditLog(ext, ups);

            TalkEvent event = new TalkEvent();
            event.setEventId(entity.getEventId());
            event.setAccount(entity.getAccount());
            event.setParent(entity.getParent());
            event.setExt(ext.toString());
            event.setDeleteTime(now);
            event.setUpdateTime(now);
            event.setUpdate(update);

            if (this.talkRepo.updateEvent(event) > 0) {
                BeanUtils.copyProperties(entity, event, "ext", "spam", "deleteTime", "updateTime");
//                this.talkLogic.postDeleteEvent(event);
                return update.getId();
            }
        }
        return null;
    }

    @Override
    public String recoveryEvent(String eventId) {
        return this.recoveryEvent(new Update(eventId));
    }

    @Override
    public String recoveryEvent(Update update) {

        TalkEventEntity entity = this.talkRepo.getTalkEventDao().get(update.getId());
        if (entity != null && entity.getDeleteTime() != 0) {
            long now = Now.millis();
            update.setTime(now);
            String ups = Gsons.toJson(update);

            JsonObject ext = Gsons.parseJsonObject(entity.getExt());
            TalkUtil.auditLog(ext, ups);

            TalkEvent event = new TalkEvent();
            event.setEventId(entity.getEventId());
            event.setAccount(entity.getAccount());
            event.setParent(entity.getParent());
            event.setExt(ext.toString());
            event.setDeleteTime(0L);
            event.setUpdateTime(now);
            event.setUpdate(update);
            event.setEventTime(now);

            if (this.talkRepo.updateEvent(event) > 0) {
                BeanUtils.copyProperties(entity, event, "ext", "spam", "deleteTime", "updateTime");
                event.setEventTime(now);
                return update.getId();
            }
        }
        return null;
    }


    @Override
    public TalkEvent getEvent(String eventId) {
        return this.talkRepo.getEvent(eventId);
    }

    @Override
    public List<TalkEvent> getEvent(List<String> eventIds) {
        return this.talkRepo.getEvent(eventIds);
    }

    @Override
    public List<TalkEvent> listEvent(String eventId, Page page) {
        String name = TalkUtil.getTalkCommentName(eventId);
        return this.talkRepo.getEventByEventTuples(this.talkRepo.getTalkEventDao().list(eventId, EventTier.COMMENTS,
                page.getMinTime(), page.getMaxTime(), page.getOffset(), page.getCount(), page.getOrderType()));
    }

    @Override
    public List<KeyTuple> listKeyEvent(String inboxName, long maxTime, int count) throws StatusException {
        Page page = new Page(null, maxTime, null, count, OrderType.DESC);
        List<KeyTuple> tuples = this.inboxService.list(inboxName, page);
        return tuples;
    }

    @Override
    public List<TalkEvent> listEvent(Set<String> inboxNames, long maxTime, int count) {
        Page page = new Page(null, maxTime, null, count, OrderType.DESC);
        List<InboxTuple> tuples = this.inboxService.list(inboxNames, page);
        return this.talkRepo.getEventByInboxTuples(tuples);
    }

    @Override
    public TalkEvent getClaim(String userId, String parent) {
        List<TalkEvent> likes = this.getClaim(userId, Collections.singleton(parent));
        if (likes != null && likes.size() > 0) {
            return likes.get(0);
        }
        return null;
    }

    @Override
    public TalkEvent getBrowse(String userId, String parent) {
        List<TalkEvent> events = this.getBrowse(userId, Collections.singleton(parent));
        if (events != null && events.size() > 0) {
            return events.get(0);
        }
        return null;
    }

    @Override
    public List<TalkEvent> getClaim(String userId, Set<String> parents) {
        List<EventTuple> tuples = this.talkRepo.getTalkEventDao().getClaim(userId, parents);
        return this.talkRepo.getEventByEventTuples(tuples);
    }

    @Override
    public List<TalkEvent> getBrowse(String userId, Set<String> parents) {
        List<EventTuple> tuples = this.talkRepo.getTalkEventDao().getBrowse(userId, parents);
        return this.talkRepo.getEventByEventTuples(tuples);
    }

    @Override
    public TalkEvent getCollect(String userId, String eventId) {
        List<TalkEvent> likes = this.getCollect(userId, Collections.singleton(eventId));
        if (likes != null && likes.size() > 0) {
            return likes.get(0);
        }
        return null;
    }

    @Override
    public List<TalkEvent> getCollect(String userId, Set<String> eventIds) {
        List<EventTuple> tuples = this.talkRepo.getTalkEventDao().getCollect(userId, eventIds);
        return this.talkRepo.getEventByEventTuples(tuples);
    }

    @Override
    public List<TalkEvent> listBrowse(String phone, Page page) throws StatusException {
        return this.talkRepo.getEventByEventTuples(this.talkRepo.getTalkEventDao().list(phone,
                EventTier.BROWSES, null, EventPrivilege.TALK, page.getMinTime(), page.getMaxTime(),
                page.getOffset(), page.getLimit(), page.getOrderType(), ValidFlag.VALID));
    }

    @Override
    public List<TalkEvent> listCollect(String phone, Page page) throws StatusException {
        return this.talkRepo.getEventByEventTuples(this.talkRepo.getTalkEventDao().list(phone,
                EventTier.COLLECTORS, null, EventPrivilege.TALK, page.getMinTime(), page.getMaxTime(),
                page.getOffset(), page.getLimit(), page.getOrderType(), ValidFlag.VALID));
    }

    @Override
    public List<TalkEvent> listClain(String identifierId, Page page) throws StatusException {
        return this.talkRepo.getEventByEventTuples(this.talkRepo.getTalkEventDao().list(identifierId,
                EventTier.CLAIMS, null, EventPrivilege.TALK, page.getMinTime(), page.getMaxTime(),
                page.getOffset(), page.getLimit(), page.getOrderType(), ValidFlag.VALID));
    }

    @Override
    public List<TalkEvent> listComment(String eventId, Page page) throws StatusException {
        return this.talkRepo.getEventByEventTuples(this.talkRepo.getTalkEventDao().list(eventId, EventTier.COMMENTS,
                page.getMinTime(), page.getMaxTime(), page.getOffset(), page.getCount(), page.getOrderType()));
    }

    @Override
    public List<TalkEvent> listMyComment(String userId, Page page) throws StatusException {
        return this.talkRepo.getEventByEventTuples(this.talkRepo.getTalkEventDao().list(userId,
                EventTier.COMMENTS, null, EventPrivilege.TALK, page.getMinTime(), page.getMaxTime(),
                page.getOffset(), page.getCount(), page.getOrderType(), ValidFlag.VALID));
    }


    @Override
    public void updatePrivilege(List<String> eventIds, Integer privilege) {
        this.talkRepo.getTalkEventDao().updatePrivilege(eventIds, privilege);
    }

    @Override
    public void updateReply(List<String> eventIds) {
        this.talkRepo.getTalkEventDao().updateReply(eventIds);

    }

}
